import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.HashMap;

import javax.swing.JOptionPane;

public class NCTClient extends Thread {
	private String host;
	Socket mySocket = null;
    PrintWriter out = null;
    BufferedReader in = null;
    String playerName;
    HashMap<String, Hand> hands;
	private int port;
	
	public NCTClient(String host, String playerName, int port) {
		this.port = port;
		this.host = host;
		try {
			
            mySocket = new Socket(host, port);
            out = new PrintWriter(mySocket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(mySocket.getInputStream()));
            hands = new HashMap<String, Hand>();
            hands.put(playerName, new Hand());
            this.playerName = playerName;
            out.println(playerName);
        } catch (UnknownHostException e) {
            System.err.println("Don't know about host: " + host);
            System.exit(1);
        } catch (IOException e) {
            System.err.println("Couldn't get I/O for the connection to: "+host);
            System.exit(1);
        }
		
	}
	
	public void closeConnection() {
		//out.println("quit"); //Breaks all connections
	}
	
	public Hand getOwnHand(){
		return getHand(playerName);
	}
	
	public Hand getHand(String pPlayer){
		return hands.get(pPlayer);
	}
	
	public void addHand(String pPlayer, Hand pHand){
		hands.put(pPlayer, pHand);
	}
	
    public void run() {
        BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
        String fromServer;
        try {
        	//syncMe();
	        while ((fromServer = in.readLine()) != null) {
	        	System.out.println("Server: " + fromServer);
	        	handleInput(fromServer);
	            if (fromServer.equals("quit"))
	                break;
	        }
	        out.close();
	        in.close();
	        stdIn.close();
	        mySocket.close();
        } catch (IOException e) {
        	System.out.println("Couldn't connect to server.");
        }
    }
    public void sendJoin() {
    	out.println("join "  + playerName);
    }
    public void sendChat(String pChat){
    	out.println("say" + playerName + ": " + pChat);
    }
    
    public void sendInc(int pI, String pCounter){
    	out.println("inc " + pCounter + " " + pI);
    }
    
    public void sendCreateCounter(String pName, int pX, int pY){
    	out.println("createcounter " + pName + " " + pX + " " + pY);
    }
    
    public void sendFlip(String pName){
    	out.println("flip " + pName + " " + playerName);
    }
    
    public void sendCreateStack(String pName, int pX, int pY, String cards){
    	out.println("createstack " + pName + " " + pX + " " + pY + " " + cards);
    }
    
    public void sendMoveObject(String pName, int pX, int pY){
    	out.println("move " + pName + " " + pX + " " + pY);
    }
    
    public void syncMe(){
    	out.println("syncMe " + playerName);
    }
    
    public void sendShuffle(String pName){
    	out.println("shuffle "+pName + " " + playerName);
    }
    
    public void sendCardToTable(String pCard, String pStack, int pI){
    	out.println("puttable "+pCard + " " + pStack + " " + playerName + " " + pI);
    }
    
    /**
     * sends the message to the server, this client draws a card from the named Stack
     * @param pName name of the Stack
     */
    public void sendDrawCard(String pName){
    	System.out.println("in draw");
    	out.println("draw "+pName + " " + playerName);
    }
    
    /**
     * sends the message to the server, to reveal the top cards of the given stack
     * @param pStack name of the Stack
     * @param pI number of cards
     */
    public void sendReveal(String pStack, int pI){
    	System.out.println("in draw");
    	out.println("reveal "+playerName+ " " + pStack + " " + pI);
    }
    
    /**
     * handels all input String recieved by the Server
     * @param input the msg to handle
     */
    public void handleInput(String input){
    	if(input.startsWith("say", 0)){
    		Game.getGame().getLog().addChat(input.substring(3));
    	}
    	else if(input.startsWith("inc")){
    		int endOfName = input.lastIndexOf(' ');
    		String name = input.substring(4,endOfName);
    		int dif = Integer.parseInt(input.substring(endOfName+1,input.length()));
    		Game.getGame().cardtable.getCounter(name).increment(dif);
    		StringBuffer prefix;
    		if(dif<0){
    			prefix =new StringBuffer("de");
    		}
    		else{
    			prefix=new StringBuffer("in");
    		}
    		Game.getGame().getLog().addLog(new StringBuffer(playerName).append(" " + prefix +"cresead ").append(" Counter ").append(name).append(" by ").append(dif).append("\n").toString());
    	}
    	else if(input.startsWith("puttable")){
    		String[] msg = input.split(" ");
    		String cardName = msg[1];
    		String stack = msg[2];
    		String name = msg[3];
    		int index = Integer.parseInt(msg[4]);
    		Card card = hands.get(name).getCardAt(index);
    		card.switchClickable();
    		hands.get(name).removeCard(card);
    		if(Game.getGame().cardtable.getCardStack(stack) == null){
    			String[] cards = null; 
    			Game.getGame().cardtable.addStack(stack, 0, 0, cards);
    			Game.getGame().cardtable.getCardStack(stack).insertOnTop(card);
    		}
    		else{
    			Game.getGame().cardtable.getCardStack(stack).insertOnTop(card);
    		}
    		hands.get(name).removeCard(card);
    		Game.getGame().getLog().addLog(new StringBuffer(name).append(" put ").append(card.getName()).append(" on the stack ").append(stack).append("\n").toString());
    		Game.getGame().playerTable.incrHand(name, -1);
    		Game.getGame().gui.validate();
    		Game.getGame().gui.repaint();
    	}
    	else if(input.startsWith("createcounter")){
    		int endOfName = input.indexOf(' ', 14);
    		int startOfY = input.lastIndexOf(' ');
    		String name = input.substring(14,endOfName);
    		int X = Integer.parseInt(input.substring(endOfName+1, startOfY));
    		int Y = Integer.parseInt(input.substring(startOfY+1, input.length()));
    		Game.getGame().cardtable.addCounter(name, X, Y);
    		Game.getGame().getLog().addLog(new StringBuffer("Counter ").append(name).append(" was created by ").append(playerName).toString());
    		
    	}
    	else if(input.startsWith("createstack")){
    		String[] msg = input.split(" ");
    		String name = msg[1];
    		int X = Integer.parseInt(msg[2]);
    		int Y = Integer.parseInt(msg[3]);
    		String[] cards;
    		System.out.println(msg.length);
    		if(msg.length > 4){
    			cards = new String[msg.length-4];
    			for(int i = 0; i < cards.length; ++i){
    				cards[i] = msg[i+4];
    			}
    			Game.getGame().cardtable.addStack(name, X, Y, cards);
    		}
    		else{
    			Game.getGame().cardtable.addStack(name, X, Y, null);
    		}		
    		Game.getGame().getLog().addLog(new StringBuffer("Stack ").append(name).append(" was created by ").append(playerName).toString());
    		
    	}
    	else if(input.startsWith("draw")){
    		int endName = input.lastIndexOf(" ");
    		String stackName = input.substring(5,endName);
    		String player = input.substring(endName+1, input.length());
    		Card draw =Game.getGame().cardtable.getCardStack(stackName).draw();
    		if(draw!=null){
    			for(String k: hands.keySet()){
    				System.out.println(k + ": " + hands.get(k));
    			}
    			draw.switchClickable();
	    		hands.get(player).addCard(draw);
	    		Game.getGame().playerTable.incrHand(player, 1);
	    		StringBuffer msg = new StringBuffer(player).append(" drawed the top card from ").append(stackName);
	    		Game.getGame().getLog().addLog(msg.toString());
	    		//TODO increase Card Numbers by one
    		}
    	}
    	else if(input.startsWith("move")){
    		int endOfName = input.indexOf(' ', 5);
    		int startOfY = input.lastIndexOf(' ');
    		String name = input.substring(5,endOfName);
    		int X = Integer.parseInt(input.substring(endOfName+1, startOfY));
    		int Y = Integer.parseInt(input.substring(startOfY+1, input.length()));
    		Game.getGame().cardtable.moveObject(name, X, Y);
    	}
    	else if(input.startsWith("shuffled")){
    		int endOfName = input.indexOf(' ', 9);
    		int endOfPlayer = input.indexOf(' ', endOfName+1);
    		String stackName = input.substring(9,endOfName);
    		System.out.println(endOfPlayer);
    		System.out.println(input);
    		String player = input.substring(endOfName+1, endOfPlayer);
    		String[] shuffelString = input.substring(endOfPlayer+1, input.length()).split(" ");
    		int[] shuffleNumber=  new int[shuffelString.length];
    		for(int i = 0; i<shuffleNumber.length; ++i){
    			shuffleNumber[i] = Integer.parseInt(shuffelString[i]);
    		}
    		Game.getGame().cardtable.getCardStack(stackName).shuffle(shuffleNumber);
    		StringBuffer msg = new StringBuffer(player).append(" shuffled ").append(stackName);
    		Game.getGame().getLog().addLog(msg.toString());
    	}
    	else if(input.startsWith("sync")){
    		try{
    			in.close();
    			ObjectInputStream syncStream = new ObjectInputStream(mySocket.getInputStream());
    			Game.getGame().cardtable = (CardTable)syncStream.readObject();
    			syncStream.close();
    			in = new BufferedReader(new InputStreamReader(mySocket.getInputStream()));
    		}
    		catch(IOException e){
    			System.out.println("could not sync!");
    		} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				System.out.println("You did BULLSHIT!");
			}
    	}
    	else if(input.startsWith("flip")){
    		String stack = input.split(" ")[1];
    		Game.getGame().cardtable.getCardStack(stack).switchRevealed();
    		Game.getGame().getLog().addLog(input.split(" ")[2] +" flipped Stack " + stack);
    	}
    	else if(input.startsWith("join")){
    		String name = input.substring(5);
    		Game.getGame().addPlayer(name);
    	}
    	else if(input.startsWith("reveal")){
    		String player = input.split(" ")[1];
    		String stackname = input.split(" ")[2];
    		int number = Integer.parseInt(input.split(" ")[3]);
    		Game.getGame().cardtable.getCardStack(stackname).revealTop(number, player);
    	}
    }
}
